package claim.layer;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.geotools.geometry.jts.LiteShape;

import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;

import claim.geom.Feature;
import claim.geom.PolygonFeature;
import claim.geoobj.Buffer;
import claim.geoobj.ClassConfiguration;
import claim.geoobj.TransitionZone;

public class CachedFeatureLayer extends FeatureLayer {

	private boolean updateRaster = true;
	private Map<String, BufferedImage> rasters;
	private int rasterWidth = 100;
	private int rasterHeight = 100;
	private double scaleFactorX, scaleFactorY;

	public CachedFeatureLayer(Collection<PolygonFeature> features,
			ClassConfiguration classConfig) {
		this(features, classConfig, 100, 100);
	}
			
	public CachedFeatureLayer(Collection<PolygonFeature> features,
			ClassConfiguration classConfig, int numPointsX, int numPointsY) {
		super(features, classConfig);
		this.rasterWidth = numPointsX;
		this.rasterHeight = numPointsY;
		this.setRasters(new HashMap<String, BufferedImage>());
		double coordWidth = this.getBoundingBox().getEnvelopeInternal()
				.getWidth();
		double coordHeight = this.getBoundingBox().getEnvelopeInternal()
				.getHeight();
		this.scaleFactorX = (rasterWidth-1) / coordWidth;
		this.scaleFactorY = (rasterHeight-1) / coordHeight;
	}

	@Override
	public double getMembership(String objClass, double x, double y) throws NullPointerException {
		int localX = (int) Math.round(x * scaleFactorX);
		int localY = (int) Math.round(y * scaleFactorY);
		BufferedImage raster = this.getRasters().get(objClass);
		int value = raster.getRaster().getSample(localX, localY, 0);
		if (value == 100) {
			return 0;
		} else if (value == 200) {
			return 1;
		} else {
			Collection<TransitionZone> zones = this.transitionZonesMap.get(objClass);
			for (TransitionZone zone : zones) {
				if (zone.getId().compareTo(zone.getObjId() +"."+ value)==0) {
					return zone.getMembership(x, y);
				}
			}
			return 0;
		}
	}

	@Override
	public void createBuffers() {
		super.createBuffers();
	}


	public void writeBuffersInCache() {
		for (String className : getClassNames()) {
			Collection<TransitionZone> zones = this.transitionZonesMap.get(className);
			this.getRasters().put(className, createRaster(className));
		}
	}

	private BufferedImage createRaster(String className) {
		BufferedImage image = new BufferedImage(rasterWidth, rasterHeight, BufferedImage.TYPE_INT_RGB);
		Graphics2D g2d = (Graphics2D) image.getGraphics();
		g2d.setColor(new Color(100, 100, 100));
		g2d.fillRect(0, 0, image.getWidth()-1, image.getHeight()-1);
		AffineTransform transform = g2d.getTransform(); // returns a copy
		transform.scale(scaleFactorX, scaleFactorY);
		Collection<PolygonFeature> features = featureByClassMap.get(className);
		for (PolygonFeature feature : features) {
			g2d.setColor(new Color(200, 200, 200));
			drawGeometry(g2d, feature.getPolygon(), transform);
			Collection<Buffer> buffers = buffersMap.get(feature.getId());
			for (Buffer buffer : buffers) {
				String id = buffer.getId();
				String[] parts = id.split("\\.");
				int other = Integer.parseInt(parts[parts.length-1]);
				g2d.setColor(new Color(other, other, other));
				drawGeometry(g2d, buffer.getGeometry(), transform);
			}
		}
		
		return image;
	}

	public void drawGeometry(Graphics2D g2d, Geometry geom, AffineTransform transform) {
		LiteShape shape = new LiteShape(geom, transform, false);
		g2d.fill(shape);
	}

	public void setRasters(Map<String, BufferedImage> rasters) {
		this.rasters = rasters;
	}

	public Map<String, BufferedImage> getRasters() {
		return rasters;
	}

}
